/*

 * Licensed to the Apache Software Foundation (ASF) under one

 * or more contributor license agreements.  See the NOTICE file

 * distributed with this work for additional information

 * regarding copyright ownership.  The ASF licenses this file

 * to you under the Apache License, Version 2.0 (the

 * "License"); you may not use this file except in compliance

 * with the License.  You may obtain a copy of the License at

 *

 *     http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */

package com.bff.gaia.unified.sdk.transforms.xjoin.core.utils;



import com.fasterxml.jackson.databind.ObjectMapper;

import java.math.BigDecimal;

import java.util.ArrayList;

import java.util.List;

import java.util.Map;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

import com.bff.gaia.unified.sdk.transforms.xjoin.core.enums.ColumnType;

import com.bff.gaia.unified.vendor.guava.com.google.common.base.Strings;

import com.bff.gaia.unified.vendor.guava.com.google.common.collect.Maps;

import org.apache.commons.lang3.StringUtils;



/**

 * Project Name: gaia-parent Description: Data: 2019/7/20 9:41

 *

 * @author tiger

 * @version v1.0

 */

public class DtStringUtil {



  private static final Pattern NO_VERSION_PATTERN = Pattern.compile("([a-zA-Z]+).*");



  private static ObjectMapper objectMapper = new ObjectMapper();



  /**

   * Split the specified string delimiter --- ignored quotes delimiter

   *

   * @param str

   * @param delimiter

   * @return

   */

  public static List<String> splitIgnoreQuota(String str, char delimiter) {

    List<String> tokensList = new ArrayList<>();

    boolean inQuotes = false;

    boolean inSingleQuotes = false;

    StringBuilder b = new StringBuilder();

    for (char c : str.toCharArray()) {

      if (c == delimiter) {

        if (inQuotes) {

          b.append(c);

        } else if (inSingleQuotes) {

          b.append(c);

        } else {

          tokensList.add(b.toString());

          b = new StringBuilder();

        }

      } else if (c == '\"') {

        inQuotes = !inQuotes;

        b.append(c);

      } else if (c == '\'') {

        inSingleQuotes = !inSingleQuotes;

        b.append(c);

      } else {

        b.append(c);

      }

    }



    tokensList.add(b.toString());



    return tokensList;

  }



  /**

   * * Split the specified string delimiter --- ignored in brackets and quotation marks delimiter

   *

   * @param str

   * @param delimter

   * @return

   */

  public static String[] splitIgnoreQuotaBrackets(String str, String delimter) {

    String splitPatternStr =

        delimter + "(?![^()]*+\\))(?![^{}]*+})(?![^\\[\\]]*+\\])(?=(?:[^\"]|\"[^\"]*\")*$)";

    return str.split(splitPatternStr);

  }



  public static String replaceIgnoreQuota(String str, String oriStr, String replaceStr) {

    String splitPatternStr = oriStr + "(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)(?=(?:[^']*'[^']*')*[^']*$)";

    return str.replaceAll(splitPatternStr, replaceStr);

  }



  public static String col2string(Object column, String type) {

    String rowData = column.toString();

    ColumnType columnType = ColumnType.valueOf(type.toUpperCase());

    Object result = null;

    switch (columnType) {

      case TINYINT:

        result = Byte.valueOf(rowData);

        break;

      case SMALLINT:

        result = Short.valueOf(rowData);

        break;

      case INT:

        result = Integer.valueOf(rowData);

        break;

      case BIGINT:

        result = Long.valueOf(rowData);

        break;

      case FLOAT:

        result = Float.valueOf(rowData);

        break;

      case DOUBLE:

        result = Double.valueOf(rowData);

        break;

      case DECIMAL:

        result = new BigDecimal(rowData);

        break;

      case STRING:

      case VARCHAR:

      case CHAR:

        result = rowData;

        break;

      case BOOLEAN:

        result = Boolean.valueOf(rowData);

        break;

      case DATE:

        result = DateUtil.dateToString((java.util.Date) column);

        break;

      case TIMESTAMP:

        result = DateUtil.timestampToString((java.util.Date) column);

        break;

      default:

        throw new IllegalArgumentException();

    }

    return result.toString();

  }



  public static String getPluginTypeWithoutVersion(String engineType) {



    Matcher matcher = NO_VERSION_PATTERN.matcher(engineType);

    if (!matcher.find()) {

      return engineType;

    }



    return matcher.group(1);

  }



  /**

   * add specify params to dbUrl

   *

   * @param dbUrl

   * @param addParams

   * @param isForce true:replace exists param

   * @return

   */

  public static String addJdbcParam(String dbUrl, Map<String, String> addParams, boolean isForce) {



    if (Strings.isNullOrEmpty(dbUrl)) {

      throw new RuntimeException("dburl can't be empty string, please check it.");

    }



    if (addParams == null || addParams.size() == 0) {

      return dbUrl;

    }



    String[] splits = dbUrl.split("\\?");

    String preStr = splits[0];

    Map<String, String> params = Maps.newHashMap();

    if (splits.length > 1) {

      String existsParamStr = splits[1];

      String[] existsParams = existsParamStr.split("&");

      for (String oneParam : existsParams) {

        String[] kv = oneParam.split("=");

        if (kv.length != 2) {

          throw new RuntimeException("illegal dbUrl:" + dbUrl);

        }



        params.put(kv[0], kv[1]);

      }

    }



    for (Map.Entry<String, String> addParam : addParams.entrySet()) {

      if (!isForce && params.containsKey(addParam.getKey())) {

        continue;

      }



      params.put(addParam.getKey(), addParam.getValue());

    }



    // rebuild dbURL

    StringBuilder sb = new StringBuilder();

    boolean isFirst = true;

    for (Map.Entry<String, String> param : params.entrySet()) {

      if (!isFirst) {

        sb.append("&");

      }



      sb.append(param.getKey()).append("=").append(param.getValue());

      isFirst = false;

    }



    return preStr + "?" + sb.toString();

  }



  public static boolean isJosn(String str) {

    boolean flag = false;

    if (StringUtils.isNotBlank(str)) {

      try {

        objectMapper.readValue(str, Map.class);

        flag = true;

      } catch (Throwable e) {

        flag = false;

      }

    }

    return flag;

  }

}